home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / dns / checker / new_named / ns_resp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-24  |  41.7 KB  |  1,789 lines

  1. /*
  2.  * Copyright (c) 1986, 1988, 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:  ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)ns_resp.c    4.63 (Berkeley) 6/1/90";
  22. #endif /* not lint */
  23.  
  24. #include <stdio.h>
  25. #include <sys/param.h>
  26. #include <sys/time.h>
  27. #include <sys/socket.h>
  28. #include <sys/file.h>
  29. #include <netinet/in.h>
  30. #include <syslog.h>
  31. #include <arpa/nameser.h>
  32. #include "ns.h"
  33. #include "db.h"
  34.  
  35. extern    int    debug;
  36. extern    FILE    *ddt;
  37. extern    int errno;
  38. extern    u_char *dnptrs[];
  39. extern    time_t retrytime();
  40. extern    struct    fwdinfo *fwdtab;
  41. extern    struct    sockaddr_in from_addr;    /* Source addr of last packet */
  42. extern    int needs_prime_cache;
  43. extern    int priming;
  44.  
  45. #ifdef CHECKER
  46. extern  u_long checker();
  47. #endif
  48.  
  49. struct qinfo *sysquery();
  50.  
  51. ns_resp(msg, msglen)
  52.     u_char *msg;
  53.     int msglen;
  54. {
  55.     register struct qinfo *qp;
  56.     register HEADER *hp;
  57.     register struct qserv *qs;
  58.     register struct databuf *ns, *ns2;
  59.     register u_char *cp;
  60.     struct    databuf *nsp[NSMAX], **nspp;
  61.     int i, c, n, ancount, aucount, nscount, arcount;
  62.     int type, class, dbflags;
  63.     int cname = 0; /* flag for processing cname response */
  64.     int count, founddata, foundname;
  65.     int buflen;
  66.     int newmsglen;
  67.     char name[MAXDNAME], *dname;
  68.     char *fname;
  69.     u_char newmsg[BUFSIZ];
  70.     u_char **dpp, *tp;
  71.     time_t rtrip;
  72.  
  73.     struct hashbuf *htp;
  74.     struct namebuf *np;
  75.     struct netinfo *lp;
  76.     extern struct netinfo *local();
  77.     extern int nsid;
  78.     extern int addcount;
  79.     struct fwdinfo *fwd;
  80.  
  81. #ifdef STATS
  82.     stats[S_RESPONSES].cnt++;
  83. #endif
  84.     hp = (HEADER *) msg;
  85.     if ((qp = qfindid(hp->id)) == NULL ) {
  86. #ifdef DEBUG
  87.         if (debug > 1)
  88.             fprintf(ddt,"DUP? dropped (id %d)\n", ntohs(hp->id));
  89. #endif
  90. #ifdef STATS
  91.         stats[S_DUPRESP].cnt++;
  92. #endif
  93.         return;
  94.     }
  95.  
  96. #ifdef DEBUG
  97.     if (debug >= 2)
  98.         fprintf(ddt,"%s response nsid=%d id=%d\n",
  99.             qp->q_system ? "SYSTEM" : "USER",
  100.             ntohs(qp->q_nsid), ntohs(qp->q_id));
  101. #endif
  102.  
  103.     /*
  104.      *  Here we handle bad responses from servers.
  105.      *  Several possibilities come to mind:
  106.      *    The server is sick and returns SERVFAIL
  107.      *    The server returns some garbage opcode (its sick)
  108.      *    The server can't understand our query and return FORMERR
  109.      *  In all these cases, we simply drop the packet and force
  110.      *  a retry.  This will make him look bad due to unresponsiveness.
  111.      *  Be sure not to include authoritative NXDOMAIN
  112.      */
  113.     if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN)
  114.         || (hp->rcode == NXDOMAIN && !hp->aa)
  115.         || hp->opcode != QUERY) {
  116. #ifdef DEBUG
  117.         if (debug >= 2)
  118.             fprintf(ddt,"resp: error (ret %d, op %d), dropped\n",
  119.                 hp->rcode, hp->opcode);
  120. #endif
  121. #ifdef STATS
  122.         stats[S_BADRESPONSES].cnt++;
  123. #endif
  124.         return;
  125.     }
  126.  
  127. #ifdef LAME_DELEGATION
  128.     /*
  129.      *  Non-authoritative, no answer, no error
  130.      */
  131.     if (hp->rcode == NOERROR && !hp->aa && ntohs(hp->ancount) == 0 &&
  132.          ntohs(hp->nscount) > 0) {
  133.         char qname[MAXDNAME];
  134.  
  135.         cp = msg + sizeof(HEADER);
  136.         dpp = dnptrs;
  137.         *dpp++ = msg;
  138.         if ((*cp & INDIR_MASK) == 0)
  139.             *dpp++ = cp;
  140.         *dpp = NULL;
  141.         if (hp->qdcount) {
  142.             n = dn_expand(msg, msg + msglen, cp, qname, sizeof(qname));
  143.                 if (n <= 0)
  144.                 goto formerr;
  145.             cp += n;
  146.             GETSHORT(type, cp);
  147.             GETSHORT(class, cp);
  148.             if (cp - msg > msglen)
  149.                 goto formerr;
  150.         }
  151.         if ((n = dn_expand(msg, msg + msglen, cp, name, sizeof(name))) < 0) {
  152.             goto formerr;
  153.         }
  154.         cp += n;
  155.         GETSHORT(type, cp);
  156.         if (type == T_NS && strlen(name) <= strlen(qp->q_domain)) {
  157.             syslog(LOG_NOTICE, "Lame delegation to '%s' received from %s (purported server for '%s') on query on name [%s]\n",
  158.                 name, inet_ntoa(from_addr.sin_addr),
  159.                 qp->q_domain, qname);
  160.             return;
  161.         }
  162.     }
  163. #endif /* LAME_DELEGATION */
  164.  
  165. #ifdef ALLOW_UPDATES
  166.     if ( (hp->rcode == NOERROR) &&
  167.          (hp->opcode == UPDATEA || hp->opcode == UPDATED ||
  168.           hp->opcode == UPDATEDA || hp->opcode == UPDATEM ||
  169.           hp->opcode == UPDATEMA) ) {
  170.         /*
  171.          * Update the secondary's copy, now that the primary
  172.          * successfully completed the update.  Zone doesn't matter
  173.          * for dyn. update -- doupdate calls findzone to find it
  174.          */
  175.         doupdate(qp->q_msg, qp->q_msglen, qp->q_msg + sizeof(HEADER),
  176.              0, (struct databuf *)0, 0);
  177. #ifdef DEBUG
  178.         if (debug >= 3)
  179.             fprintf(ddt,"resp: leaving, UPDATE*\n");
  180. #endif
  181.         /* return code filled in by doupdate */
  182.         goto return_msg;
  183.     }
  184. #endif ALLOW_UPDATES
  185.  
  186.     /*
  187.      * Determine if the response came from a forwarder.  Packets from
  188.      * anyplace not listed as a forwarder or as a server to whom we
  189.      * might have forwarded the query will be dropped.
  190.      */
  191.     for (fwd = fwdtab; fwd != (struct fwdinfo *)NULL; fwd = fwd->next)
  192.         if (bcmp((char *)&fwd->fwdaddr.sin_addr, &from_addr.sin_addr,
  193.             sizeof(struct in_addr)) == 0)
  194.             break;
  195.     /*
  196.      * If we were using nameservers, find the qinfo pointer and update
  197.      * the rtt and fact that we have called on this server before.
  198.      */
  199.     if (fwd == (struct fwdinfo *)NULL) {
  200.         struct timeval *stp;
  201.  
  202.         for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++)
  203.             if (bcmp((char *)&qs->ns_addr.sin_addr,
  204.                 &from_addr.sin_addr, sizeof(struct in_addr)) == 0)
  205.                 break;
  206.         if (n >= qp->q_naddr) {
  207. #ifdef DEBUG
  208.             if (debug)
  209.                 fprintf(ddt, "Response from unexpected source %s\n",
  210.                 inet_ntoa(from_addr.sin_addr));
  211. #endif DEBUG
  212. #ifdef STATS
  213.             stats[S_MARTIANS].cnt++;
  214. #endif
  215.             /* 
  216.              * We don't know who this response came from so it
  217.              * gets dropped on the floor.
  218.              */
  219.             return;
  220.         }
  221.         stp = &qs->stime;
  222.  
  223.         /* Handle response from different (untried) interface */
  224.         if (stp->tv_sec == 0) {
  225.             ns = qs->ns;
  226.             while (qs > qp->q_addr &&
  227.                 (qs->stime.tv_sec == 0 || qs->ns != ns))
  228.                 qs--;
  229.             *stp = qs->stime;
  230. #ifdef DEBUG
  231.             if (debug)
  232.                 fprintf(ddt,
  233.                 "Response from unused address %s, assuming %s\n",
  234.                 inet_ntoa(from_addr.sin_addr),
  235.                 inet_ntoa(qs->ns_addr.sin_addr));
  236. #endif DEBUG
  237.         }
  238.  
  239.         /* compute query round trip time */
  240.         rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 +
  241.             (tt.tv_usec - stp->tv_usec) / 1000);
  242.         
  243. #ifdef DEBUG
  244.         if (debug > 2)
  245.             fprintf(ddt,"stime %d/%d  now %d/%d rtt %d\n",
  246.                 stp->tv_sec, stp->tv_usec,
  247.                 tt.tv_sec, tt.tv_usec, rtrip);
  248. #endif
  249.         /* prevent floating point overflow, limit to 1000 sec */
  250.         if (rtrip > 1000000)
  251.                 rtrip = 1000000;
  252.         ns = qs->nsdata;
  253.         /*
  254.          * Don't update nstime if this doesn't look
  255.          * like an address databuf now.            XXX
  256.          */
  257.         if (ns->d_type == T_A && ns->d_class == qs->ns->d_class) {
  258.             if (ns->d_nstime == 0)
  259.                 ns->d_nstime = (u_long)rtrip;
  260.             else
  261.                 ns->d_nstime = ns->d_nstime * ALPHA +
  262.                     (1-ALPHA) * (u_long)rtrip;
  263.             /* prevent floating point overflow, limit to 1000 sec */
  264.             if (ns->d_nstime > 1000000)
  265.                 ns->d_nstime = 1000000;
  266.         }
  267.  
  268.         /*
  269.          * Record the source so that we do not use this NS again.
  270.          */
  271.         if(qp->q_nusedns < NSMAX) {
  272.             qp->q_usedns[qp->q_nusedns++] = qs->ns;
  273. #ifdef DEBUG
  274.             if(debug > 1)
  275.                 fprintf(ddt, "NS #%d addr %s used, rtt %d\n",
  276.                 n, inet_ntoa(qs->ns_addr.sin_addr),
  277.                 ns->d_nstime);
  278. #endif DEBUG
  279.         }
  280.  
  281.         /*
  282.          * Penalize those who had earlier chances but failed
  283.          * by multiplying round-trip times by BETA (>1).
  284.          * Improve nstime for unused addresses by applying GAMMA.
  285.          * The GAMMA factor makes unused entries slowly
  286.          * improve, so they eventually get tried again.
  287.          * GAMMA should be slightly less than 1.
  288.          * Watch out for records that may have timed out
  289.          * and are no longer the correct type.            XXX
  290.          */
  291.         
  292.         for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++) {
  293.             ns2 = qs->nsdata;
  294.             if (ns2 == ns)
  295.                 continue;
  296.             if (ns2->d_type != T_A ||
  297.                 ns2->d_class != qs->ns->d_class)    /* XXX */
  298.                 continue;
  299.             if (qs->stime.tv_sec) {
  300.                 if (ns2->d_nstime == 0)
  301.                 ns2->d_nstime = rtrip * BETA;
  302.                 else
  303.                 ns2->d_nstime =
  304.                     ns2->d_nstime * BETA + (1-ALPHA) * rtrip;
  305.                 if (ns2->d_nstime > 1000000)
  306.                 ns2->d_nstime = 1000000;
  307.             } else
  308.                 ns2->d_nstime = ns2->d_nstime * GAMMA;
  309. #ifdef DEBUG
  310.             if(debug > 1)
  311.                 fprintf(ddt, "NS #%d %s rtt now %d\n", n,
  312.                 inet_ntoa(qs->ns_addr.sin_addr),
  313.                 ns2->d_nstime);
  314. #endif DEBUG
  315.         }
  316.     }
  317.  
  318.     /*
  319.      * Skip query section
  320.      */
  321.     addcount = 0;
  322.     cp = msg + sizeof(HEADER);
  323.     dpp = dnptrs;
  324.     *dpp++ = msg;
  325.     if ((*cp & INDIR_MASK) == 0)
  326.         *dpp++ = cp;
  327.     *dpp = NULL;
  328.     if (hp->qdcount) {
  329.         n = dn_skipname(cp, msg + msglen);
  330.             if (n <= 0)
  331.             goto formerr;
  332.         cp += n;
  333.         GETSHORT(type, cp);
  334.         GETSHORT(class, cp);
  335.         if (cp - msg > msglen)
  336.             goto formerr;
  337.     }
  338.  
  339.     /*
  340.      * Save answers, authority, and additional records for future use.
  341.      */
  342.     ancount = ntohs(hp->ancount);
  343.     aucount = ntohs(hp->nscount);
  344.     arcount = ntohs(hp->arcount);
  345.     nscount = 0;
  346.     tp = cp;
  347. #ifdef DEBUG
  348.     if (debug >= 3)
  349.         fprintf(ddt,"resp: ancount %d, aucount %d, arcount %d\n",
  350.             ancount, aucount, arcount);
  351. #endif
  352.  
  353.     /*
  354.      *  If there's an answer, check if it's a CNAME response;
  355.      *  if no answer but aucount > 0, see if there is an NS
  356.      *  or just an SOA.  (NOTE: ancount might be 1 with a CNAME,
  357.      *  and NS records may still be in the authority section;
  358.      *  we don't bother counting them, as we only use nscount
  359.      *  if ancount == 0.)
  360.      */
  361.     if (ancount == 1 || (ancount == 0 && aucount > 0)) {
  362.         c = aucount;
  363.         do {
  364.             if (tp - msg >= msglen)
  365.                 goto formerr;
  366.             n = dn_skipname(tp, msg + msglen);
  367.             if (n <= 0)
  368.                 goto formerr;
  369.             tp += n;          /* name */
  370.             GETSHORT(i, tp);    /* type */
  371.             tp += sizeof(u_short);    /* class */
  372.             tp += sizeof(u_long);    /* ttl */
  373.             GETSHORT(count, tp);     /* dlen */
  374.             if (tp - msg > msglen - count)
  375.                 goto formerr;
  376.             tp += count;
  377.             if (ancount && i == T_CNAME) {
  378.                 cname++;
  379. #ifdef DEBUG
  380.                 if (debug)
  381.                     fprintf(ddt,"CNAME - needs more processing\n");
  382. #endif
  383.                 if (!qp->q_cmsglen) {
  384.                     qp->q_cmsg = qp->q_msg;
  385.                     qp->q_cmsglen = qp->q_msglen;
  386.                     qp->q_msg = NULL;
  387.                     qp->q_msglen = 0;
  388.                 }
  389.             }
  390.             /*
  391.              * See if authority record is a nameserver.
  392.              */
  393.             if (ancount == 0 && i == T_NS)
  394.                 nscount++;
  395.         } while (--c > 0);
  396.         tp = cp;
  397.     }
  398.  
  399.     /*
  400.      * Add the info received in the response to the Data Base
  401.      */
  402.     c = ancount + aucount + arcount;
  403. #ifdef notdef
  404.     /*
  405.      * If the request was for a CNAME that doesn't exist,
  406.      * but the name is valid, fetch any other data for the name.
  407.      * DON'T do this now, as it will requery if data are already
  408.      * in the cache (maybe later with negative caching).
  409.      */
  410.     if (hp->qdcount && type == T_CNAME && c == 0 && hp->rcode == NOERROR &&
  411.        !qp->q_system) {
  412. #ifdef DEBUG
  413.         if (debug >= 3)
  414.             fprintf(ddt,"resp: leaving, no CNAME\n");
  415. #endif
  416.         /* Cause us to put it in the cache later */
  417.         prime(class, T_ANY, qp);
  418.  
  419.         /* Nothing to store, just give user the answer */
  420.         goto return_msg;
  421.     }
  422. #endif /* notdef */
  423.  
  424.     nspp = nsp;
  425.     if (qp->q_system)
  426.         dbflags = DB_NOTAUTH | DB_NODATA;
  427.     else
  428.         dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS;
  429.     for (i = 0; i < c; i++) {
  430.         struct databuf *ns3;
  431.  
  432.         if (cp >= msg + msglen)
  433.             goto formerr;
  434.         ns3 = 0;
  435.         if ((n = doupdate(msg, msglen, cp, 0, &ns3, dbflags)) < 0) {
  436. #ifdef DEBUG
  437.             if (debug)
  438.                 fprintf(ddt,"resp: leaving, doupdate failed\n");
  439. #endif
  440.             /* return code filled in by doupdate */
  441.             goto return_msg;
  442.         }
  443.         /*
  444.          * Remember nameservers from the authority section
  445.          * for referrals.
  446.          * (This is usually overwritten by findns below(?). XXX
  447.          */
  448.         if (ns3 && i >= ancount && i < ancount + aucount &&
  449.             nspp < &nsp[NSMAX-1])
  450.             *nspp++ = ns3;
  451.         cp += n;
  452.     }
  453.  
  454.     if (qp->q_system && ancount) {
  455.         if (qp->q_system == PRIMING_CACHE)
  456.             check_root();
  457. #ifdef DEBUG
  458.         if (debug > 2)
  459.             fprintf(ddt,"resp: leaving, SYSQUERY ancount %d\n", ancount);
  460. #endif
  461.         qremove(qp);
  462.         return;
  463.     }
  464.  
  465.     if (cp > msg + msglen)
  466.         goto formerr;
  467.  
  468.     /*
  469.      *  If there are addresses and this is a local query,
  470.      *  sort them appropriately for the local context.
  471.      */
  472.     if (ancount > 1 && (lp = local(&qp->q_from)) != NULL) 
  473.         sort_response(tp, ancount, lp, msg + msglen);
  474.  
  475.     /*
  476.      * An answer to a T_ANY query or a successful answer to a
  477.      * regular query with no indirection, then just return answer.
  478.      */
  479.     if ((hp->qdcount && type == T_ANY && ancount) ||
  480.         (!cname && !qp->q_cmsglen && ancount)) {
  481. #ifdef DEBUG
  482.         if (debug >= 3)
  483.             fprintf(ddt,"resp: got as much answer as there is\n");
  484. #endif
  485.         goto return_msg;
  486.     }
  487.  
  488.     /*
  489.      * Eventually we will want to cache this negative answer.
  490.      */
  491.     if (ancount == 0 && nscount == 0 &&
  492.         (hp->aa || fwd || class == C_ANY)) {
  493.         /* We have an authoritative NO */
  494. #ifdef DEBUG
  495.         if (debug >= 3)
  496.             fprintf(ddt,"resp: leaving auth NO\n");
  497. #endif
  498.         if (qp->q_cmsglen) {
  499.             msg = (u_char *)qp->q_cmsg;
  500.             msglen = qp->q_cmsglen;
  501.             hp = (HEADER *)msg;
  502.         }
  503.         goto return_msg;
  504.     }
  505.  
  506.     /*
  507.      * All messages in here need further processing.  i.e. they
  508.      * are either CNAMEs or we got referred again.
  509.      */
  510.     count = 0;
  511.     founddata = 0;
  512.     foundname = 0;
  513.     dname = name;
  514.     if (!cname && qp->q_cmsglen && ancount) {
  515. #ifdef DEBUG
  516.         if (debug)
  517.             fprintf(ddt,"Cname second pass\n");
  518. #endif
  519.         newmsglen = qp->q_cmsglen;
  520.         bcopy(qp->q_cmsg, newmsg, newmsglen);
  521.     } else {
  522.         newmsglen = msglen;
  523.         bcopy(msg, newmsg, newmsglen);
  524.     }
  525.     hp = (HEADER *) newmsg;
  526.     hp->ancount = 0;
  527.     hp->nscount = 0;
  528.     hp->arcount = 0;
  529.     dnptrs[0] = newmsg;
  530.     dnptrs[1] = NULL;
  531.     cp = newmsg + sizeof(HEADER);
  532.     if (cname)
  533.         cp += dn_skipname(cp, newmsg + newmsglen) + QFIXEDSZ;
  534.     if ((n = dn_expand(newmsg, newmsg + newmsglen,
  535.         cp, dname, sizeof(name))) < 0) {
  536. #ifdef DEBUG
  537.         if (debug)
  538.             fprintf(ddt,"dn_expand failed\n" );
  539. #endif
  540.         goto servfail;
  541.     }
  542.     if (!cname)
  543.         cp += n + QFIXEDSZ;
  544.     buflen = sizeof(newmsg) - (cp - newmsg);
  545.  
  546. try_again:
  547. #ifdef DEBUG
  548.     if (debug)
  549.         fprintf(ddt,"resp: nlookup(%s) type=%d\n",dname, type);
  550. #endif
  551.     fname = "";
  552.     htp = hashtab;        /* lookup relative to root */
  553.     np = nlookup(dname, &htp, &fname, 0);
  554. #ifdef DEBUG
  555.     if (debug)
  556.         fprintf(ddt,"resp: %s '%s' as '%s' (cname=%d)\n",
  557.             np == NULL ? "missed" : "found", dname, fname, cname);
  558. #endif
  559.     if (np == NULL || fname != dname)
  560.         goto fetch_ns;
  561.  
  562.     foundname++;
  563.     count = cp - newmsg;
  564.     n = finddata(np, class, type, hp, &dname, &buflen, &count);
  565.     if (n == 0)
  566.         goto fetch_ns;        /* NO data available */
  567.     cp += n;
  568.     buflen -= n;
  569.     hp->ancount += count;
  570.     if (fname != dname && type != T_CNAME && type != T_ANY) {
  571.         cname++;
  572.         goto try_again;
  573.     }
  574.     founddata = 1;
  575.  
  576. #ifdef DEBUG
  577.     if (debug >= 3) {
  578.         fprintf(ddt,"resp: foundname = %d count = %d ", foundname, count);
  579.         fprintf(ddt,"founddata = %d cname = %d\n", founddata, cname);
  580.     }
  581. #endif
  582.  
  583. fetch_ns:
  584.     hp->ancount = htons(hp->ancount);
  585.     /*
  586.       * Look for name servers to refer to and fill in the authority
  587.       * section or record the address for forwarding the query
  588.       * (recursion desired).
  589.       */
  590.     switch (findns(&np, class, nsp, &count)) {
  591.     case NXDOMAIN:        /* shouldn't happen */
  592. #ifdef DEBUG
  593.         if (debug >= 3)
  594.             fprintf(ddt,"req: leaving (%s, rcode %d)\n",
  595.                 dname, hp->rcode);
  596. #endif
  597.         if (!foundname)
  598.             hp->rcode = NXDOMAIN;
  599.         if (class != C_ANY) {
  600.             hp->aa = 1;
  601.             /*
  602.              * should return SOA if founddata == 0,
  603.              * but old named's are confused by an SOA
  604.              * in the auth. section if there's no error.
  605.              */
  606.             if (foundname == 0 && np) {
  607.                 n = doaddauth(hp, cp, buflen, np, nsp[0]);
  608.                 cp += n;
  609.                 buflen -= n;
  610.             }
  611.         }
  612.         goto return_newmsg;
  613.  
  614.     case SERVFAIL:
  615.         goto servfail;
  616.     }
  617.  
  618.     if (founddata) {
  619.         hp = (HEADER *)newmsg;
  620.         n = add_data(np, nsp, cp, buflen);
  621.         if (n < 0) {
  622.             hp->tc = 1;
  623.             n = (-n);
  624.         }
  625.         cp += n;
  626.         buflen -= n;
  627.         hp->nscount = htons((u_short)count);
  628.         goto return_newmsg;
  629.     }
  630.  
  631.     /*
  632.      *  If we get here, we don't have the answer yet and are about
  633.      *  to iterate to try and get it.  First, infinite loop avoidance.
  634.      */
  635.     if (qp->q_nqueries++ > MAXQUERIES) {
  636. #ifdef DEBUG
  637.         if (debug)
  638.             fprintf(ddt,"resp: MAXQUERIES exceeded (%s, class %d, type %d)\n",
  639.             dname, class, type);
  640. #endif
  641.         syslog(LOG_NOTICE,
  642.                     "MAXQUERIES exceeded, possible data loop in resolving (%s)",
  643.                 dname);
  644.         goto servfail;
  645.     }
  646.  
  647.     /* Reset the query control structure */
  648.     qp->q_naddr = 0;
  649.     qp->q_curaddr = 0;
  650.     qp->q_fwd = fwdtab;
  651. #ifdef LAME_DELEGATION
  652.     getname(np, qp->q_domain, sizeof(qp->q_domain));
  653. #endif /* LAME_DELEGATION */
  654.     if (nslookup(nsp, qp) == 0) {
  655. #ifdef DEBUG
  656.         if (debug >= 3)
  657.             fprintf(ddt,"resp: no addrs found for NS's\n");
  658. #endif
  659.         goto servfail;
  660.     }
  661.     for (n = 0; n < qp->q_naddr; n++)
  662.         qp->q_addr[n].stime.tv_sec = 0;
  663.     if (!qp->q_fwd)
  664.         qp->q_addr[0].stime = tt;
  665.     if (cname) {
  666.          if (qp->q_cname++ == MAXCNAMES) {
  667. #ifdef DEBUG
  668.             if (debug >= 3)
  669.                 fprintf(ddt,"resp: leaving, MAXCNAMES exceeded\n");
  670. #endif
  671.             goto servfail;
  672.          }
  673. #ifdef DEBUG
  674.          if (debug)
  675.              fprintf(ddt,"q_cname = %d\n",qp->q_cname);
  676.         if (debug >= 3)
  677.                fprintf(ddt,"resp: building recursive query; nslookup\n");
  678. #endif
  679.         if (qp->q_msg)
  680.             (void) free(qp->q_msg);
  681.         if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {
  682. #ifdef DEBUG
  683.             if (debug)
  684.                 fprintf(ddt,"resp: malloc error\n");
  685. #endif
  686.             goto servfail;
  687.         }
  688.         qp->q_msglen = res_mkquery(QUERY, dname, class,
  689.             type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);
  690.         hp = (HEADER *) qp->q_msg;
  691.             hp->rd = 0;
  692.     } else
  693.         hp = (HEADER *)qp->q_msg;
  694.     hp->id = qp->q_nsid = htons((u_short)++nsid);
  695.     if (qp->q_fwd)
  696.         hp->rd = 1;
  697.     unsched(qp);
  698.     schedretry(qp, retrytime(qp));
  699. #ifdef DEBUG
  700.     if (debug)
  701.         fprintf(ddt,"resp: forw -> %s %d (%d) nsid=%d id=%d %dms\n",
  702.             inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),
  703.             ds, ntohs(Q_NEXTADDR(qp,0)->sin_port),
  704.             ntohs(qp->q_nsid), ntohs(qp->q_id),
  705.             qp->q_addr[0].nsdata->d_nstime);
  706.     if ( debug >= 10)
  707.         fp_query(msg, ddt);
  708. #endif
  709.     if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
  710.         (struct sockaddr *)Q_NEXTADDR(qp,0),
  711.         sizeof(struct sockaddr_in)) < 0) {
  712. #ifdef DEBUG
  713.         if (debug >= 5)
  714.             fprintf(ddt, "sendto error = %d\n", errno);
  715. #endif
  716.     }
  717.     hp->rd = 0;    /* leave set to 0 for dup detection */
  718. #ifdef STATS
  719.     stats[S_OUTPKTS].cnt++;
  720. #endif
  721. #ifdef DEBUG
  722.     if (debug >= 3)
  723.         fprintf(ddt,"resp: Query sent.\n");
  724. #endif
  725.     return;
  726.  
  727. formerr:
  728. #ifdef DEBUG
  729.     if (debug)
  730.         fprintf(ddt,"FORMERR resp() from %s size err %d, msglen %d\n",
  731.         inet_ntoa(from_addr.sin_addr),
  732.         cp-msg, msglen);
  733. #endif
  734.     syslog(LOG_INFO, "Malformed response from %s\n",
  735.         inet_ntoa(from_addr.sin_addr));
  736. #ifdef STATS
  737.     stats[S_RESPFORMERR].cnt++;
  738. #endif
  739.     return;
  740.  
  741. return_msg:
  742. #ifdef STATS
  743.     stats[S_RESPOK].cnt++;
  744. #endif
  745.     /* The "standard" return code */
  746.     hp->qr = 1;
  747.     hp->id = qp->q_id;
  748.     hp->rd = 1;
  749.     hp->ra = 1;
  750.     (void) send_msg(msg, msglen, qp);
  751.     qremove(qp);
  752.     return;
  753.  
  754. return_newmsg:
  755. #ifdef STATS
  756.     stats[S_RESPOK].cnt++;
  757. #endif
  758.     if (addcount) {
  759.         n = doaddinfo(hp, cp, buflen);
  760.         cp += n;
  761.         buflen -= n;
  762.     }
  763.  
  764.     hp->id = qp->q_id;
  765.     hp->rd = 1;
  766.     hp->ra = 1;
  767.     hp->qr = 1;
  768.     (void) send_msg(newmsg, cp - newmsg, qp);
  769.     qremove(qp);
  770.     return;
  771.  
  772. servfail:
  773. #ifdef STATS
  774.     stats[S_RESPFAIL].cnt++;
  775. #endif
  776.     hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);
  777.     hp->rcode = SERVFAIL;
  778.     hp->id = qp->q_id;
  779.     hp->rd = 1;
  780.     hp->ra = 1;
  781.     hp->qr = 1;
  782.     (void) send_msg((char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen), qp);
  783.     qremove(qp);
  784.     return;
  785. }
  786.  
  787. /*
  788.  * Decode the resource record 'rrp' and update the database.
  789.  * If savens is true, record pointer for forwarding queries a second time.
  790.  */
  791. doupdate(msg, msglen, rrp, zone, savens, flags)
  792.     char *msg;
  793.     u_char *rrp;
  794.     struct databuf **savens;
  795.     int  msglen, zone, flags;
  796. {
  797.     register u_char *cp;
  798.     register int n;
  799.     int class, type, dlen, n1;
  800.     u_long ttl;
  801.     struct databuf *dp;
  802.     char dname[MAXDNAME];
  803.     u_char *cp1;
  804.     u_char data[BUFSIZ];
  805.     register HEADER *hp = (HEADER *) msg;
  806. #ifdef ALLOW_UPDATES
  807.     int zonenum;
  808. #endif
  809.  
  810. #ifdef DEBUG
  811.     if (debug > 2)
  812.         fprintf(ddt,"doupdate(zone %d, savens %x, flags %x)\n",
  813.             zone, savens, flags);
  814. #endif
  815.  
  816.     cp = rrp;
  817.     if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0) {
  818.         hp->rcode = FORMERR;
  819.         return (-1);
  820.     }
  821.     cp += n;
  822.     GETSHORT(type, cp);
  823.     GETSHORT(class, cp);
  824.     GETLONG(ttl, cp);
  825.     GETSHORT(dlen, cp);
  826. #ifdef DEBUG
  827.     if (debug > 2)
  828.         fprintf(ddt,"doupdate: dname %s type %d class %d ttl %d\n",
  829.             dname, type, class, ttl);
  830. #endif
  831.     /*
  832.      * Convert the resource record data into the internal
  833.      * database format.
  834.      */
  835.     switch (type) {
  836.     case T_A:
  837.     case T_WKS:
  838.     case T_HINFO:
  839.     case T_UINFO:
  840.     case T_UID:
  841.     case T_GID:
  842.     case T_TXT:
  843. #ifdef ALLOW_T_UNSPEC
  844.     case T_UNSPEC:
  845. #endif ALLOW_T_UNSPEC
  846.         cp1 = cp;
  847.         n = dlen;
  848.         cp += n;
  849.         break;
  850.  
  851.     case T_CNAME:
  852.     case T_MB:
  853.     case T_MG:
  854.     case T_MR:
  855.     case T_NS:
  856.     case T_PTR:
  857.         if ((n = dn_expand(msg, msg + msglen, cp, data,
  858.            sizeof(data))) < 0) {
  859.             hp->rcode = FORMERR;
  860.             return (-1);
  861.         }
  862.         cp += n;
  863.         cp1 = data;
  864.         n = strlen(data) + 1;
  865.         break;
  866.  
  867.     case T_MINFO:
  868.     case T_SOA:
  869.         if ((n = dn_expand(msg, msg + msglen, cp, data,
  870.             sizeof(data))) < 0) {
  871.             hp->rcode = FORMERR;
  872.             return (-1);
  873.         }
  874.         cp += n;
  875.         cp1 = data + (n = strlen(data) + 1);
  876.         n1 = sizeof(data) - n;
  877.         if (type == T_SOA)
  878.             n1 -= 5 * sizeof(u_long);
  879.         if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) {
  880.             hp->rcode = FORMERR;
  881.             return (-1);
  882.         }
  883.         cp += n;
  884.         cp1 += strlen(cp1) + 1;
  885.         if (type == T_SOA) {
  886.             bcopy(cp, cp1, n = 5 * sizeof(u_long));
  887.             cp += n;
  888.             cp1 += n;
  889.         }
  890.         n = cp1 - data;
  891.         cp1 = data;
  892.         break;
  893.  
  894.     case T_MX:
  895.         /* grab preference */
  896.         bcopy(cp,data,sizeof(u_short));
  897.         cp1 = data + sizeof(u_short);
  898.         cp += sizeof(u_short);
  899.  
  900.         /* get name */
  901.         if ((n = dn_expand(msg, msg + msglen, cp, cp1,
  902.             sizeof(data)-sizeof(u_short))) < 0)
  903.             return(-1);
  904.         cp += n;
  905.  
  906.         /* compute end of data */
  907.         cp1 += strlen(cp1) + 1;
  908.         /* compute size of data */
  909.         n = cp1 - data;
  910.         cp1 = data;
  911.         break;
  912.  
  913.     default:
  914. #ifdef DEBUG
  915.         if (debug >= 3)
  916.             fprintf(ddt,"unknown type %d\n", type);
  917. #endif
  918.         return ((cp - rrp) + dlen);
  919.     }
  920.     if (n > MAXDATA) {
  921. #ifdef DEBUG
  922.         if (debug)
  923.             fprintf(ddt,
  924.             "update type %d: %d bytes is too much data\n",
  925.             type, n);
  926. #endif
  927.         hp->rcode = NOCHANGE;    /* XXX - FORMERR ??? */
  928.         return(-1);
  929.     }
  930.  
  931. #ifdef ALLOW_UPDATES
  932.     /*
  933.      * If this is a dynamic update request, process it specially; else,
  934.      * execute normal update code.
  935.      */
  936.     switch(hp->opcode) {
  937.  
  938.     /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */
  939.     case UPDATEM:
  940.     case UPDATEMA:
  941.  
  942.     /*
  943.      * The named code for UPDATED and UPDATEDA is the same except that for
  944.      * UPDATEDA we we ignore any data that was passed: we just delete all
  945.      * RRs whose name, type, and class matches
  946.      */
  947.     case UPDATED:
  948.     case UPDATEDA:
  949.         if (type == T_SOA) {    /* Not allowed */
  950. #ifdef DEBUG
  951.             if (debug)
  952.                fprintf(ddt, "UDPATE: REFUSED - SOA delete\n");
  953. #endif
  954.             hp->rcode = REFUSED;
  955.             return(-1);
  956.         }
  957.         /*
  958.          * Don't check message length if doing UPDATEM/UPDATEMA,
  959.          * since the whole message wont have been demarshalled until
  960.          * we reach the code for UPDATEA
  961.          */
  962.         if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) {
  963.             if (cp != (u_char *)(msg + msglen)) {
  964. #ifdef DEBUG
  965.                 if (debug)
  966.                     fprintf(ddt,"FORMERR UPDATE message length off\n");
  967. #endif
  968.                 hp->rcode = FORMERR;
  969.                 return(-1);
  970.             }
  971.         }
  972.         if ((zonenum = findzone(dname, class)) == 0) { 
  973.             hp->rcode = NXDOMAIN;
  974.             return(-1);
  975.         }
  976.         if (zones[zonenum].z_state & Z_DYNADDONLY) {
  977.             hp->rcode = NXDOMAIN;
  978.             return(-1);
  979.         }
  980.         if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) {
  981.             /* Make a dp for use in db_update, as old dp */
  982.             dp = savedata(class, type, 0, cp1, n);
  983.             dp->d_zone = zonenum;
  984.             n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE,
  985.                       hashtab);
  986.             if (n != OK) {
  987. #ifdef DEBUG
  988.                 if (debug)
  989.                     fprintf(ddt,"UPDATE: db_update failed\n");
  990. #endif DEBUG
  991.                 free( (struct databuf *) dp);
  992.                 hp->rcode = NOCHANGE;
  993.                 return(-1);
  994.             }
  995.         } else {    /* UPDATEDA or UPDATEMA */
  996.             int DeletedOne = 0;
  997.             /* Make a dp for use in db_update, as old dp */
  998.             dp = savedata(class, type, 0, NULL, 0);
  999.             dp->d_zone = zonenum;
  1000.             do {    /* Loop and delete all matching RR(s) */
  1001.                 n = db_update(dname, dp, NULL, DB_DELETE,
  1002.                           hashtab);
  1003.                 if (n != OK)
  1004.                     break;
  1005.                 DeletedOne++;
  1006.             } while (1);
  1007.             free( (struct databuf *) dp);
  1008.             /* Ok for UPDATEMA not to have deleted any RRs */
  1009.             if (!DeletedOne && hp->opcode == UPDATEDA) {
  1010. #ifdef DEBUG
  1011.                 if (debug)
  1012.                     fprintf(ddt,"UPDATE: db_update failed\n");
  1013. #endif DEBUG
  1014.                 hp->rcode = NOCHANGE;
  1015.                 return(-1);
  1016.             }
  1017.         }
  1018.         if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) )
  1019.             return (cp - rrp);;
  1020.         /*
  1021.          * Else unmarshal the RR to be added and continue on to
  1022.          * UPDATEA code for UPDATEM/UPDATEMA
  1023.          */
  1024.         if ((n =
  1025.            dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) {
  1026. #ifdef DEBUG
  1027.             if (debug)
  1028.                 fprintf(ddt,"FORMERR UPDATE expand name failed\n");
  1029. #endif
  1030.             hp->rcode = FORMERR;
  1031.             return(-1);
  1032.         }
  1033.         cp += n;
  1034.         GETSHORT(type, cp);
  1035.         GETSHORT(class, cp);
  1036.         GETLONG(ttl, cp);
  1037.         GETSHORT(n, cp);
  1038.         cp1 = cp;
  1039. /**** XXX - need bounds checking here ****/
  1040.         cp += n;
  1041.  
  1042.     case UPDATEA:
  1043.         if (n > MAXDATA) {
  1044. #ifdef DEBUG
  1045.             if (debug)
  1046.                 fprintf(ddt,"UPDATE: too much data\n");
  1047. #endif
  1048.             hp->rcode = NOCHANGE;
  1049.             return(-1);
  1050.         }
  1051.         if (cp != (u_char *)(msg + msglen)) {
  1052. #ifdef DEBUG
  1053.             if (debug)
  1054.                 fprintf(ddt,"FORMERR UPDATE message length off\n");
  1055. #endif
  1056.             hp->rcode = FORMERR;
  1057.             return(-1);
  1058.         }
  1059.         if ((zonenum = findzone(dname, class)) == 0) { 
  1060.             hp->rcode = NXDOMAIN;
  1061.             return(-1);
  1062.         }
  1063.         if (zones[zonenum].z_state & Z_DYNADDONLY) {
  1064.             struct hashbuf *htp = hashtab;
  1065.             char *fname;
  1066.             if (nlookup(dname, &htp, &fname, 0) &&
  1067.                 !strcmp(dname, fname)) {
  1068. #ifdef    DEBUG
  1069.                 if (debug)
  1070.                 fprintf(ddt,"refusing add of existing name\n");
  1071. #endif
  1072.                 hp->rcode = REFUSED;
  1073.                 return(-1);
  1074.             }
  1075.         }
  1076.         dp = savedata(class, type, ttl, cp1, n);
  1077.         dp->d_zone = zonenum;
  1078.         if ((n = db_update(dname, NULL, dp, DB_NODATA,
  1079.                    hashtab)) != OK) {
  1080. #ifdef DEBUG
  1081.             if (debug)
  1082.                 fprintf(ddt,"UPDATE: db_update failed\n");
  1083. #endif
  1084.             hp->rcode = NOCHANGE;
  1085.             return (-1);
  1086.         }
  1087.         else
  1088.             return (cp - rrp);
  1089.     }
  1090. #endif ALLOW_UPDATES
  1091.  
  1092.     if (zone == 0)
  1093.         ttl += tt.tv_sec;
  1094. #ifdef TRACEROOT
  1095.     /*
  1096.      *  This is a variation on a theme which was posted by
  1097.      *  pma@cnd.hp.com.  It not only records who is giving out
  1098.      *  bogus root NS records, it also prevents them from 
  1099.      *  polluting our cache.
  1100.      */
  1101.     if ((type == T_NS) && (savens != NULL)) {
  1102.         char *rindex();
  1103.         char qname[MAXDNAME], *temp;
  1104.         int bogus = 1, qn;
  1105.         struct fwdinfo *fwd;
  1106.  
  1107.         temp = rindex(data, '.');
  1108.         if (temp != NULL)
  1109.             bogus = (strcasecmp(temp, ".arpa") == 0);
  1110.         qname[0] = '\0';
  1111.         qname[1] = '\0';
  1112.         qn = dn_expand(msg, msg + msglen, msg + sizeof(HEADER), qname,
  1113.                 sizeof(qname));
  1114.         if (qn < 0)
  1115.             qname[0] = '?';
  1116.         else if (qname[0] == '\0')
  1117.             qname[0] = '.';
  1118.         if ((dname[0] == '\0') && (zone == 0) &&
  1119.             (bogus || strcmp(qname, "."))) {
  1120.             if (bogus) {
  1121.                 syslog(LOG_NOTICE, "Bogus root NS %s received from %s on query on name [%s] -- rejected\n",
  1122.                     data, inet_ntoa(from_addr.sin_addr), qname);
  1123.                 return(cp - rrp);
  1124.             } else {
  1125.                 /*
  1126.                  * Don't log legitimate root server RR's from
  1127.                  * our forwarder, just hope it's healthy.
  1128.                  */
  1129.                 for (fwd = fwdtab; fwd != NULL; fwd = fwd->next)
  1130.                     if (bcmp((char *)&fwd->fwdaddr.sin_addr,
  1131.                         &from_addr.sin_addr,
  1132.                         sizeof(struct in_addr)) == 0)
  1133.                         break;
  1134.                 if ( fwd == NULL )
  1135.                     syslog(LOG_NOTICE, "Root NS %s received from %s on query on name [%s]\n",
  1136.                         data, inet_ntoa(from_addr.sin_addr),
  1137.                         qname);
  1138.             }
  1139.         }
  1140.     }
  1141. #endif
  1142.     dp = savedata(class, type, ttl, cp1, n);
  1143.     dp->d_zone = zone;
  1144.     if ((n = db_update(dname, dp, dp, flags, hashtab)) < 0) {
  1145. #ifdef DEBUG
  1146.         if (debug && (n != DATAEXISTS))
  1147.             fprintf(ddt,"update failed (%d)\n", n);
  1148.         else if (debug >= 3)
  1149.             fprintf(ddt,"update failed (DATAEXISTS)\n");
  1150. #endif
  1151.         (void) free((char *)dp);
  1152.     } else if (type == T_NS && savens != NULL)
  1153.         *savens = dp;
  1154.     return (cp - rrp);
  1155. }
  1156.  
  1157. send_msg(msg, msglen, qp)
  1158.     char *msg;
  1159.     int msglen;
  1160.     struct qinfo *qp;
  1161. {
  1162.     extern struct qinfo *qhead;
  1163. #ifdef DEBUG
  1164.     struct qinfo *tqp;
  1165. #endif DEBUG
  1166.  
  1167.     if (qp->q_system)
  1168.         return(1);
  1169. #ifdef DEBUG
  1170.     if (debug) {
  1171.         fprintf(ddt,"send_msg -> %s (%s %d %d) id=%d\n",
  1172.             inet_ntoa(qp->q_from.sin_addr), 
  1173.             qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP",
  1174.             qp->q_stream == QSTREAM_NULL ? qp->q_dfd
  1175.                              : qp->q_stream->s_rfd,
  1176.             ntohs(qp->q_from.sin_port),
  1177.             ntohs(qp->q_id));
  1178.     }
  1179.     if (debug>4)
  1180.         for (tqp = qhead; tqp!=QINFO_NULL; tqp = tqp->q_link) {
  1181.             fprintf(ddt, "qp %x q_id: %d  q_nsid: %d q_msglen: %d ",
  1182.                 tqp, tqp->q_id,tqp->q_nsid,tqp->q_msglen);
  1183.                 fprintf(ddt,"q_naddr: %d q_curaddr: %d\n", tqp->q_naddr,
  1184.             tqp->q_curaddr);
  1185.                 fprintf(ddt,"q_next: %x q_link: %x\n", qp->q_next,
  1186.                 qp->q_link);
  1187.         }
  1188.     if (debug >= 10)
  1189.         fp_query(msg, ddt);
  1190. #endif DEBUG
  1191. #ifdef CHECKER
  1192.         if( checker( 1, msg, msglen, &qp->q_from, qp->q_stream ) == 1 ) {
  1193.             if( qp->q_stream != QSTREAM_NULL ) sq_done(qp->q_stream); }
  1194.         else {
  1195. #endif
  1196.     if (qp->q_stream == QSTREAM_NULL) {
  1197.         if (sendto(qp->q_dfd, msg, msglen, 0,
  1198.             (struct sockaddr *)&qp->q_from, sizeof(qp->q_from)) < 0) {
  1199. #ifdef DEBUG
  1200.             if (debug)
  1201.                 fprintf(ddt, "sendto error errno= %d\n",errno);
  1202. #endif
  1203.             return(1);
  1204.         }
  1205. #ifdef STATS
  1206.         stats[S_OUTPKTS].cnt++;
  1207. #endif
  1208.     } else {
  1209.         (void) writemsg(qp->q_stream->s_rfd, msg, msglen);
  1210.         sq_done(qp->q_stream);
  1211.     }
  1212. #ifdef CHECKER
  1213.         }
  1214. #endif
  1215.     return(0);
  1216. }
  1217.  
  1218. prime(class, type, oqp)
  1219.     int class, type;
  1220.     register struct qinfo *oqp;
  1221. {
  1222.     char    dname[BUFSIZ];
  1223.  
  1224.     if (oqp->q_msg == NULL)
  1225.         return;
  1226.     if (dn_expand(oqp->q_msg, oqp->q_msg + oqp->q_msglen,
  1227.         oqp->q_msg + sizeof(HEADER), dname, sizeof(dname)) < 0)
  1228.         return;
  1229. #ifdef DEBUG
  1230.     if (debug >= 2)
  1231.            fprintf(ddt,"prime: %s\n", dname);
  1232. #endif
  1233.     (void) sysquery(dname, class, type);
  1234. }
  1235.  
  1236.  
  1237. prime_cache()
  1238. {
  1239.     register struct qinfo *qp;
  1240.  
  1241. #ifdef DEBUG
  1242.     if (debug)
  1243.         fprintf(ddt,"prime_cache: priming = %d\n", priming);
  1244. #endif
  1245. #ifdef STATS
  1246.     stats[S_PRIMECACHE].cnt++;
  1247. #endif
  1248.     if (!priming && fcachetab->h_tab[0] != NULL && !forward_only) {
  1249.         priming++;
  1250.         if ((qp = sysquery("", C_IN, T_NS)) == NULL)
  1251.             priming = 0;
  1252.         else
  1253.             qp->q_system = PRIMING_CACHE;
  1254.     }
  1255.     needs_prime_cache = 0;
  1256.     return;
  1257. }
  1258.  
  1259. struct qinfo *
  1260. sysquery(dname, class, type)
  1261.     char *dname;
  1262.     int class, type;
  1263. {
  1264.     extern struct qinfo *qhead;
  1265.     extern int nsid;
  1266.     register struct qinfo *qp, *oqp;
  1267.     register HEADER *hp;
  1268.     struct namebuf *np;
  1269.     struct databuf *nsp[NSMAX];
  1270.     struct hashbuf *htp;
  1271.     char *fname;
  1272.     int count;
  1273.  
  1274. #ifdef DEBUG
  1275.     if (debug > 2)
  1276.            fprintf(ddt,"sysquery(%s, %d, %d)\n", dname, class, type);
  1277. #endif
  1278. #ifdef STATS
  1279.     stats[S_SYSQUERIES].cnt++;
  1280. #endif
  1281.     htp = hashtab;
  1282.     if (priming && dname[0] == '\0')
  1283.         np = NULL;
  1284.     else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {
  1285. #ifdef DEBUG
  1286.         if (debug)
  1287.             fprintf(ddt,"sysquery: nlookup error on %s?\n", dname);
  1288. #endif
  1289.         return(0);
  1290.     }
  1291.  
  1292.     switch (findns(&np, class, nsp, &count)) {
  1293.     case NXDOMAIN:
  1294.     case SERVFAIL:
  1295. #ifdef DEBUG
  1296.         if (debug)
  1297.             fprintf(ddt,"sysquery: findns error on %s?\n", dname);
  1298. #endif
  1299.         return(0);
  1300.     }
  1301.  
  1302.     /* build new qinfo struct */
  1303.     qp = qnew();
  1304.     qp->q_cmsg = qp->q_msg = NULL;
  1305.     qp->q_dfd = ds;
  1306.     qp->q_fwd = fwdtab;
  1307.     qp->q_system++;
  1308. #ifdef LAME_DELEGATION
  1309.     getname(np, qp->q_domain, sizeof(qp->q_domain));
  1310. #endif /* LAME_DELEGATION */
  1311.  
  1312.     if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {
  1313.         qfree(qp);
  1314.         return(0);
  1315.     }
  1316.     qp->q_msglen = res_mkquery(QUERY, dname, class,
  1317.         type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);
  1318.     hp = (HEADER *) qp->q_msg;
  1319.     hp->id = qp->q_nsid = htons((u_short)++nsid);
  1320.     hp->rd = (qp->q_fwd ? 1 : 0);
  1321.  
  1322.     /* First check for an already pending query for this data */
  1323.     for (oqp = qhead; oqp!=QINFO_NULL; oqp = oqp->q_link) {
  1324.         if (oqp != qp && oqp->q_msglen == qp->q_msglen &&
  1325.          bcmp((char *)oqp->q_msg+2, qp->q_msg+2, qp->q_msglen-2) == 0) {
  1326. #ifdef DEBUG
  1327.             if (debug >= 3)
  1328.                 fprintf(ddt, "sysquery: duplicate\n");
  1329. #endif
  1330.             qfree(qp);
  1331.             return(0);
  1332.         }
  1333.     }
  1334.  
  1335.     if (nslookup(nsp, qp) == 0) {
  1336. #ifdef DEBUG
  1337.         if (debug)
  1338.             fprintf(ddt,"resp: no addrs found for NS's\n");
  1339. #endif
  1340.         qfree(qp);
  1341.         return(0);
  1342.     }
  1343.  
  1344.     schedretry(qp, retrytime(qp));
  1345.     if (qp->q_fwd == 0)
  1346.         qp->q_addr[0].stime = tt;
  1347.  
  1348. #ifdef DEBUG
  1349.     if (debug)
  1350.         fprintf(ddt,"sysquery: send -> %s %d (%d), nsid=%d id=%d %dms\n",
  1351.         inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),
  1352.         qp->q_dfd, ntohs(Q_NEXTADDR(qp,0)->sin_port),
  1353.         ntohs(qp->q_nsid), ntohs(qp->q_id),
  1354.         qp->q_addr[0].nsdata->d_nstime);
  1355.     if ( debug >= 10)
  1356.         fp_query(qp->q_msg, ddt);
  1357. #endif
  1358.     if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0,
  1359.         (struct sockaddr *)Q_NEXTADDR(qp,0),
  1360.         sizeof(struct sockaddr_in)) < 0){
  1361. #ifdef DEBUG
  1362.         if (debug)
  1363.         fprintf(ddt, "sendto error errno= %d\n",errno);
  1364. #endif
  1365.     }
  1366. #ifdef STATS
  1367.     stats[S_OUTPKTS].cnt++;
  1368. #endif
  1369.     return(qp);
  1370. }
  1371.  
  1372. /*
  1373.  * Check the list of root servers after receiving a response
  1374.  * to a query for the root servers.
  1375.  */
  1376. check_root()
  1377. {
  1378.     register struct databuf *dp, *pdp;
  1379.     register struct namebuf *np;
  1380.     int count = 0;
  1381.  
  1382.     priming = 0;
  1383.     for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)
  1384.         if (np->n_dname[0] == '\0')
  1385.             break;
  1386.     if (np == NULL) {
  1387.         syslog(LOG_ERR, "check_root: Can't find root!\n");
  1388.         return;
  1389.     }
  1390.     for (dp = np->n_data; dp != NULL; dp = dp->d_next)
  1391.         if (dp->d_type == T_NS)
  1392.             count++;
  1393. #ifdef DEBUG
  1394.     if (debug)
  1395.         fprintf(ddt,"%d root servers\n", count);
  1396. #endif
  1397.     if (count < MINROOTS) {
  1398.         syslog(LOG_WARNING,
  1399.         "check_root: %d root servers after query to root server < min",
  1400.             count);
  1401.         return;
  1402.     }
  1403.     pdp = NULL;
  1404.     dp = np->n_data;
  1405.     while (dp != NULL) {
  1406.         if (dp->d_type == T_NS && dp->d_zone == 0 &&
  1407.             dp->d_ttl < tt.tv_sec) {
  1408. #ifdef DEBUG
  1409.             if (debug)
  1410.                 fprintf(ddt,"deleting old root server '%s'\n",
  1411.                 dp->d_data);
  1412. #endif
  1413.             dp = rm_datum(dp, np, pdp);
  1414.             /* SHOULD DELETE FROM HINTS ALSO */
  1415.             continue;
  1416.         }
  1417.         pdp = dp;
  1418.         dp = dp->d_next;
  1419.     }
  1420.     check_ns();
  1421. }
  1422.  
  1423. /* 
  1424.  * Check the root to make sure that for each NS record we have a A RR
  1425.  */
  1426. check_ns()
  1427. {
  1428.     register struct databuf *dp, *tdp;
  1429.     register struct namebuf *np, *tnp;
  1430.     struct hashbuf *htp;
  1431.     char *dname;
  1432.     int found_arr;
  1433.     char *fname;
  1434.     time_t curtime;
  1435.  
  1436. #ifdef DEBUG
  1437.     if (debug >= 2)
  1438.            fprintf(ddt,"check_ns()\n");
  1439. #endif
  1440. #ifdef STATS
  1441.     stats[S_CHECKNS].cnt++;
  1442. #endif
  1443.  
  1444.     curtime = (u_long) tt.tv_sec;
  1445.     for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) {
  1446.         if (np->n_dname[0] != 0)
  1447.             continue;
  1448.             for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  1449.                 if (dp->d_type != T_NS)
  1450.                     continue;
  1451.  
  1452.                 /* look for A records */
  1453.             dname = dp->d_data;
  1454.             htp = hashtab;
  1455.             tnp = nlookup(dname, &htp, &fname, 0);
  1456.             if (tnp == NULL || fname != dname) {
  1457. #ifdef DEBUG
  1458.                 if (debug >= 3)
  1459.                     fprintf(ddt,"check_ns: %s: not found %s %x\n",
  1460.                     dname, fname, tnp);
  1461. #endif
  1462.                 (void) sysquery(dname, dp->d_class, T_A);
  1463.                 continue;
  1464.             }
  1465.             /* look for name server addresses */
  1466.             found_arr = 0;
  1467.             for (tdp=tnp->n_data; tdp!=NULL; tdp=tdp->d_next) {
  1468.                 if (tdp->d_type != T_A ||
  1469.                    tdp->d_class != dp->d_class)
  1470.                 continue;
  1471.                 if ((tdp->d_zone == 0) &&
  1472.                 (tdp->d_ttl < curtime)) {
  1473. #ifdef DEBUG
  1474.                     if (debug >= 3)
  1475.                         fprintf(ddt,"check_ns: stale entry '%s'\n",
  1476.                             tnp->n_dname);
  1477. #endif
  1478.                 /* Cache invalidate the address RR's */
  1479.                 delete_all(tnp, dp->d_class, T_A);
  1480.                 found_arr = 0;
  1481.                     break;
  1482.                 }
  1483.                 found_arr++;
  1484.             }
  1485.             if (!found_arr)
  1486.                 (void) sysquery(dname, dp->d_class, T_A);
  1487.             }
  1488.     }
  1489. }
  1490.  
  1491. #define    MAXCLASS 255        /* belongs elsewhere */
  1492. int    norootlogged[MAXCLASS];
  1493.  
  1494. /*
  1495.  *  Find NS's or an SOA for the given dname (np) and fill in the
  1496.  *  nsp array.  Returns OK on success, and SERVFAIL on error.
  1497.  *  We return NXDOMAIN to indicate we are authoritative.
  1498.  */
  1499. findns(npp, class, nsp, countp)
  1500.     register struct namebuf **npp;
  1501.     struct databuf **nsp;
  1502.     int *countp;
  1503. {
  1504.     register struct namebuf *np = *npp;
  1505.     register struct databuf *dp;
  1506.     register struct    databuf **nspp;
  1507.     struct hashbuf *htp = hashtab;
  1508.     
  1509.     if (priming && (np == NULL || np->n_dname[0] == '\0'))
  1510.         htp = fcachetab;
  1511. try_again:
  1512.     if (htp == fcachetab)
  1513.         needs_prime_cache = 1;
  1514.     while (np == NULL && htp != NULL) {
  1515. #ifdef DEBUG
  1516.         if (debug > 2)
  1517.             fprintf(ddt, "findns: using %s\n", htp == hashtab ?
  1518.                 "cache" : "hints");
  1519. #endif
  1520.         for (np = htp->h_tab[0]; np != NULL; np = np->n_next)
  1521.             if (np->n_dname[0] == '\0')
  1522.                 break;
  1523.         htp = (htp == hashtab ? fcachetab : NULL);    /* Fallback */
  1524.     }
  1525.     while(np != NULL) {
  1526. #ifdef DEBUG
  1527.         if (debug >= 5)
  1528.             fprintf(ddt, "findns: np 0x%x\n", np);
  1529. #endif
  1530.         /* Look first for SOA records. */
  1531.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  1532.             if (dp->d_zone != 0 && match(dp, class, T_SOA)) {
  1533. #ifdef DEBUG
  1534.                 if (debug >= 3)
  1535.                     fprintf(ddt,"findns: SOA found\n");
  1536. #endif
  1537.                 if (zones[dp->d_zone].z_auth) {
  1538.                     *npp = np;
  1539.                     nsp[0] = dp;
  1540.                     return(NXDOMAIN);
  1541.                 } else
  1542.                     return (SERVFAIL);
  1543.             }
  1544.         }
  1545.  
  1546.         /* If no SOA records, look for NS records. */
  1547.         nspp = &nsp[0];
  1548.         *nspp = NULL;
  1549.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  1550.             if (dp->d_type != T_NS ||
  1551.                 (dp->d_class != class && class != C_ANY))
  1552.                 continue;
  1553.             /*
  1554.              * Don't use records that may become invalid to
  1555.              * reference later when we do the rtt computation.
  1556.              * Never delete our safety-belt information!
  1557.              */
  1558.             if ((dp->d_zone == 0) &&
  1559.                 (dp->d_ttl < (tt.tv_sec+900)) &&
  1560.                 !(dp->d_flags & DB_F_HINT)) {
  1561. #ifdef DEBUG
  1562.                 if (debug)
  1563.                     fprintf(ddt,"findns: stale entry '%s'\n",
  1564.                             np->n_dname);
  1565. #endif
  1566.                 /* Cache invalidate the NS RR's */
  1567.                 if (dp->d_ttl < tt.tv_sec)
  1568.                     delete_all(np, class, T_NS);
  1569.                 goto try_parent;
  1570.             }
  1571.             if (nspp < &nsp[NSMAX-1])
  1572.                 *nspp++ = dp;
  1573.         }
  1574.  
  1575.         *countp = nspp - nsp;
  1576.         if (*countp > 0) {
  1577. #ifdef DEBUG
  1578.             if (debug >= 3)
  1579.                 fprintf(ddt,"findns: %d NS's added for '%s'\n",
  1580.                     *countp, np->n_dname);
  1581. #endif
  1582.             *nspp = NULL;
  1583.             *npp = np;
  1584.             return(OK);    /* Success, got some NS's */
  1585.         }
  1586. try_parent:
  1587.         np = np->n_parent;
  1588.     }
  1589.     if (htp)
  1590.         goto try_again;
  1591. #ifdef DEBUG
  1592.     if (debug)
  1593.         fprintf(ddt, "findns: No root nameservers for class %d?\n",
  1594.             class);
  1595. #endif
  1596.     if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) {
  1597.         norootlogged[class] = 1;
  1598.         syslog(LOG_ERR, "No root nameservers for class %d\n", class);
  1599.     }
  1600.     return(SERVFAIL);
  1601. }
  1602.  
  1603. /*
  1604.  *  Extract RR's from the given node that match class and type.
  1605.  *  Return number of bytes added to response.
  1606.  *  If no matching data is found, then 0 is returned.
  1607.  */
  1608. finddata(np, class, type, hp, dnamep, lenp, countp)
  1609.     struct namebuf *np;
  1610.     int class, type;
  1611.     register HEADER *hp;
  1612.     char **dnamep;
  1613.     int *lenp, *countp;
  1614. {
  1615.     register struct databuf *dp;
  1616.     register char *cp;
  1617.     int buflen, n, count = 0, foundstale = 0;
  1618.  
  1619.     buflen = *lenp;
  1620.     cp = ((char *)hp) + *countp;
  1621.     for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  1622.         if (!wanted(dp, class, type)) {
  1623.             if (type == T_CNAME && class == dp->d_class) {
  1624.                 /* any data means no CNAME exists */
  1625.                 *countp = 0;
  1626.                 return(0);
  1627.             }
  1628.             continue;
  1629.         }
  1630.         if (stale(dp)) {
  1631.             /*
  1632.              * Don't use stale data.
  1633.              * Would like to call delete_all here
  1634.              * and continue, but the data chain would get
  1635.              * munged; can't restart, as make_rr has side
  1636.              * effects (leaving pointers in dnptr).
  1637.              * Just skip this entry for now
  1638.              * and call delete_all at the end.
  1639.              */
  1640. #ifdef DEBUG
  1641.             if (debug >=3)
  1642.                fprintf(ddt,"finddata: stale entry '%s'\n",np->n_dname);
  1643. #endif
  1644.             if (dp->d_zone == 0)
  1645.                 foundstale++;
  1646.             continue;
  1647.         }
  1648.         if ((n = make_rr(*dnamep, dp, cp, buflen, 1)) < 0) {
  1649.             hp->tc = 1;
  1650.             *countp = count;
  1651.             return(*lenp - buflen);
  1652.         }
  1653.  
  1654.         cp += n;
  1655.         buflen -= n;
  1656.         count++;
  1657. #ifdef notdef
  1658.         /* this isn't right for glue records, aa is set in ns_req */
  1659.         if (dp->d_zone && zones[dp->d_zone].z_auth && class != C_ANY)
  1660.             hp->aa = 1;            /* XXX */
  1661. #endif
  1662.         if (dp->d_type == T_CNAME) {
  1663.             if (type != T_ANY) {    /* or T_NS? */
  1664.                 *dnamep = dp->d_data;
  1665.                 if (dp->d_zone && zones[dp->d_zone].z_auth &&
  1666.                     class != C_ANY)        /* XXX */
  1667.                     hp->aa = 1;        /* XXX */
  1668.             }
  1669.             break;
  1670.         }
  1671.     }
  1672.     /*
  1673.      * Cache invalidate the other RR's of same type
  1674.      * if some have timed out
  1675.      */
  1676.     if (foundstale)
  1677.         delete_all(np, class, type);
  1678. #ifdef DEBUG
  1679.     if (debug >=3)
  1680.         fprintf(ddt,"finddata: added %d class %d type %d RRs\n",
  1681.             count, class, type);
  1682. #endif
  1683.     *countp = count;
  1684.     return(*lenp - buflen);
  1685. }
  1686.  
  1687. /*
  1688.  * Do we want this data record based on the class and type?
  1689.  */
  1690. wanted(dp, class, type)
  1691.     struct databuf *dp;
  1692.     int class, type;
  1693. {
  1694.  
  1695. #ifdef DEBUG
  1696.     if (debug > 3)
  1697.         fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type,
  1698.             dp->d_class, dp->d_type);
  1699. #endif
  1700.  
  1701.     if (dp->d_class != class && class != C_ANY)
  1702.         return (0);
  1703.     if (type == dp->d_type)
  1704.         return (1);
  1705.     switch (dp->d_type) {
  1706.     case T_ANY:
  1707.     case T_CNAME:
  1708.         return (1);
  1709.     }
  1710.     switch (type) {
  1711.     case T_ANY:
  1712.         return (1);
  1713.  
  1714.     case T_MAILB:
  1715.         switch (dp->d_type) {
  1716.         case T_MR:
  1717.         case T_MB:
  1718.         case T_MG:
  1719.         case T_MINFO:
  1720.             return (1);
  1721.         }
  1722.         break;
  1723.  
  1724.     case T_AXFR:
  1725.         if (dp->d_type == T_SOA)
  1726.             return (1);
  1727.     }
  1728.     return (0);
  1729. }
  1730.  
  1731. /*
  1732.  *  Add RR entries from dpp array to a query/response.
  1733.  *  Return the number of bytes added or negative the amount
  1734.  *  added if truncation was required.  Typically you are
  1735.  *  adding NS records to a response.
  1736.  */
  1737. add_data(np, dpp, cp, buflen)
  1738.     struct namebuf *np;
  1739.     struct databuf **dpp;
  1740.     register char *cp;
  1741.     int buflen;
  1742. {
  1743.     register struct databuf *dp;
  1744.     char dname[MAXDNAME];
  1745.     register int n, count = 0;
  1746.  
  1747.     getname(np, dname, sizeof(dname));
  1748.     for(dp = *dpp++; dp != NULL; dp = *dpp++) {
  1749.         if (stale(dp))
  1750.             continue;    /* ignore old cache entry */
  1751.         if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0)
  1752.             return(-count);        /* Truncation */
  1753.         cp += n;
  1754.         buflen -= n;
  1755.         count += n;
  1756.     }
  1757.     return(count);
  1758. }
  1759.  
  1760. /*
  1761.  *  This is best thought of as a "cache invalidate" function.
  1762.  *  It is called whenever a piece of data is determined to have
  1763.  *  timed out.  It is better to have no information, than to
  1764.  *  have partial information you pass off as complete.
  1765.  */
  1766. delete_all(np, class, type)
  1767. register struct namebuf *np;
  1768. int class, type;
  1769. {
  1770.     register struct databuf *dp, *pdp;
  1771.  
  1772. #ifdef DEBUG
  1773.     if (debug > 2)
  1774.         fprintf(ddt,"delete_all: '%s' 0x%x class %d type %d\n",
  1775.                 np->n_dname, np, class, type);
  1776. #endif
  1777.     pdp = NULL;
  1778.     dp = np->n_data;
  1779.     while (dp != NULL) {
  1780.         if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT)
  1781.             && match(dp, class, type)) {
  1782.             dp = rm_datum(dp, np, pdp);
  1783.             continue;
  1784.         }
  1785.         pdp = dp;
  1786.         dp = dp->d_next;
  1787.     }
  1788. }
  1789.